package com.example.springstudy.config;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.example.springstudy.base.ResultCode;
import com.example.springstudy.utils.JwtUtil;
import com.example.springstudy.utils.RedisUtils;
import com.example.springstudy.utils.ResponseUtil;
import com.example.springstudy.utils.SecurityUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Slf4j
public class JwtFilter extends OncePerRequestFilter {

    RedisTemplate<String, Object> redisTemplate;

    public JwtFilter(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        try {
            String prefix = SecurityUtils.prefix;
            if(StrUtil.isNotBlank(token) && token.startsWith(prefix)) {
                token = token.substring(prefix.length());
                JWT jwt = JWTUtil.parseToken(token);
                byte[] key = JwtUtil.keyStr.getBytes(StandardCharsets.UTF_8);
                boolean isValidate = jwt.setKey(key).validate(0);
                if(!isValidate){
                    ResponseUtil.writeErrMsg(response, ResultCode.TOKEN_INVALID);
                    return;
                }
                JSONObject payload = jwt.getPayloads();
                String jwtId = payload.getStr(JWT.JWT_ID);
                boolean isTokenBlacklisted = Boolean.TRUE.equals(redisTemplate.hasKey("BLACKLIST_TOKEN_PREFIX" + jwtId));
                if (isTokenBlacklisted) {
                    ResponseUtil.writeErrMsg(response, ResultCode.TOKEN_INVALID);
                    return;
                }
                // Token 有效将其解析为 Authentication 对象，并设置到 Spring Security 上下文中
                Authentication authentication = JwtUtil.getAuthentication(payload);
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception e) {
            log.error("jwtfilter", e);
            SecurityContextHolder.clearContext();
            ResponseUtil.writeErrMsg(response, ResultCode.TOKEN_INVALID);
            return;
        }
        filterChain.doFilter(request, response);
    }
}
